using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.IO;
using Banshee.Base;
using Banshee.MediaEngine;
using Microsoft.Win32;
public static class PluginModuleEntry
{
    public static Type[] GetTypes()
    {
        return new Type[] {
            typeof(Banshee.MediaEngine.WMP10.WMP10PlayerEngine)
        };
    }
}
namespace Banshee.MediaEngine.WMP10
{
    /// <summary>
    /// Windows Media Player Based engine
    /// </summary>
    public class WMP10PlayerEngine:PlayerEngine
    {
        WMPLib.WindowsMediaPlayer Player;
        public WMP10PlayerEngine()
        {
            Player = new WMPLib.WindowsMediaPlayer();
            try
            {
                UInt32 dwValue = (UInt32)1;
                RegistryKey hkcu = Registry.CurrentUser;
                RegistryKey subkey = hkcu.OpenSubKey(@"Software\Microsoft\MediaPlayer\Preferences", true);

                subkey.SetValue("CDAutoPlay", (Int32)dwValue);

                // disable metadata lookup for CD's since we use MusicBrainz
                dwValue = (UInt32)Convert.ToInt32(subkey.GetValue("MetadataRetrieval"));
                dwValue |= 0;
                subkey.SetValue("MetadataRetrieval", (Int32)dwValue);
            }
            catch (Exception) { }
            Player.ModeChange += new WMPLib._WMPOCXEvents_ModeChangeEventHandler(Player_ModeChange);
            Player.Warning += new WMPLib._WMPOCXEvents_WarningEventHandler(Player_Warning);
            Player.PlayStateChange += new WMPLib._WMPOCXEvents_PlayStateChangeEventHandler(Player_PlayStateChange);
            Player.MediaError +=new WMPLib._WMPOCXEvents_MediaErrorEventHandler(Player_MediaError);
            Player.PositionChange += new WMPLib._WMPOCXEvents_PositionChangeEventHandler(Player_PositionChange);
            Player.StatusChange += new WMPLib._WMPOCXEvents_StatusChangeEventHandler(Player_StatusChange);
            Player.DeviceConnect += new WMPLib._WMPOCXEvents_DeviceConnectEventHandler(Player_DeviceConnect);
            Player.CdromMediaChange += new WMPLib._WMPOCXEvents_CdromMediaChangeEventHandler(Player_CdromMediaChange);
            Player.MediaChange += new WMPLib._WMPOCXEvents_MediaChangeEventHandler(Player_MediaChange);
            Player.DurationUnitChange += new WMPLib._WMPOCXEvents_DurationUnitChangeEventHandler(Player_DurationUnitChange);
            Player.EndOfStream += new WMPLib._WMPOCXEvents_EndOfStreamEventHandler(Player_EndOfStream);
            
        }

        void Player_EndOfStream(int Result)
        {
            OnEventChanged(PlayerEngineEvent.EndOfStream);
            Player.controls.stop();
            Console.WriteLine("Stream Ended");
        }

        void Player_DurationUnitChange(int NewDurationUnit)
        {
            Console.WriteLine("Duration {0}", NewDurationUnit);
        }

        void Player_MediaChange(object Item)
        {
            LogCore.Instance.PushInformation("Player Engine", string.Format(" Media changed to {0}", Position));
            OnEventChanged(PlayerEngineEvent.Iterate);
        }
        void LoadCdromDevices()
        {
            for (int i = 0; i < Player.cdromCollection.count; i++)
            {
                
                string root = Player.cdromCollection.Item(i).driveSpecifier;
                Console.WriteLine("Cdrom {0} detected", root);
            }
        }
        void Player_CdromMediaChange(int CdromNum)
        {
          /*  if (manager != null)
            {
                SetManager();
            }
        string devicename = Player.cdromCollection.Item(CdromNum).driveSpecifier;
        manager.OnMediaChanged(devicename);
        Console.WriteLine("Media Changed:{0}", devicename);*/
            
        }

        void Player_DeviceConnect(WMPLib.IWMPSyncDevice pDevice)
        {
            Console.WriteLine("Device connect:{0}", pDevice.friendlyName);
        }

        void Player_Warning(int WarningType, int Param, string Description)
        {
           Console.WriteLine("Player warning:{0}",Description);
        }

        void Player_ModeChange(string ModeName, bool NewValue)
        {
            Console.WriteLine("Mode {0}:{1}", ModeName, NewValue);
        }

        void Player_StatusChange()
        {
           Console.WriteLine("Player Status:{0}", Player.status);
        }

        void Player_PositionChange(double oldPosition, double newPosition)
        {
            OnEventChanged(PlayerEngineEvent.Iterate);
        }

        void Player_MediaError(object pMediaObject)
        {
            Console.WriteLine("Player Media Error:{0}", pMediaObject.ToString());
        }

        void Player_PlayStateChange(int NewState)
        {
            if ((WMPLib.WMPPlayState)NewState == WMPLib.WMPPlayState.wmppsPlaying)
            {
                OnStateChanged(PlayerEngineState.Playing);

            }
            else if ((WMPLib.WMPPlayState)NewState == WMPLib.WMPPlayState.wmppsWaiting)
            {
                OnStateChanged(PlayerEngineState.Idle);
            }
            else if ((WMPLib.WMPPlayState)NewState == WMPLib.WMPPlayState.wmppsPaused)
            {
                OnStateChanged(PlayerEngineState.Paused);

            }
            else if ((WMPLib.WMPPlayState)NewState == WMPLib.WMPPlayState.wmppsBuffering)
            {
                OnStateChanged(PlayerEngineState.Contacting);

            }
            else if ((WMPLib.WMPPlayState)NewState == WMPLib.WMPPlayState.wmppsReady)
            {
                OnStateChanged(PlayerEngineState.Loaded);
            }

             else if ((WMPLib.WMPPlayState)NewState == WMPLib.WMPPlayState.wmppsMediaEnded)
            {
                OnEventChanged(PlayerEngineEvent.EndOfStream);
            }
            else
            {
                Console.WriteLine("State {0}", (WMPLib.WMPPlayState)NewState);
            }
           

        }
        protected override void OpenUri(SafeUri uri)
        {
            string url = uri.ToString();
            // Cornel - I use this little hack so that i dont break the Banshee base code cdda://8#G:\
            if (url.StartsWith("cdda"))
            {
                string[] res1 = url.Split(new string[] {"//"}, StringSplitOptions.None);
                string[] res2 = res1[1].Split('#');
                string tracknumber = res2[0];
                Player.currentPlaylist = Player.cdromCollection.Item(0).Playlist;
                object media = Player.currentPlaylist.get_Item(System.Convert.ToInt32(tracknumber));
                Player.controls.playItem((WMPLib.IWMPMedia)media);
            }
            else
            {
                
                Player.controls.stop();
                Player.URL = url;
                Player.controls.play();
            }
            
        }
        int vol;
        public override ushort Volume
        {
            get
            {
                return (ushort)Player.settings.volume;
            }
            set
            {
                Player.settings.volume = (int)value;

            }
        }

        public override uint Position
        {
            get
            {
                return System.Convert.ToUInt32(Player.controls.currentPosition);
            }
            set
            {
                Player.controls.currentPosition = System.Convert.ToDouble(value);
            }
        }

        public override uint Length
        {
            get { return System.Convert.ToUInt32(Player.controls.currentItem.duration); }
        }
        private static string [] source_capabilities = { "file", "http", "cdda" };
        public override IEnumerable SourceCapabilities
        {
            get { return source_capabilities; }
        }
        private static string [] decoder_capabilities = { "ogg", "wma", "asf", "flac" };
        public override IEnumerable ExplicitDecoderCapabilities
        {
            get { return decoder_capabilities;}
        }

        public override string Id
        {
            get { return "wmp10"; }
        }

        public override string Name
        {
            get { return "Windows Media Player 11"; }
        }
    }
}
